frappe.provide('frappe_wxwork');

/**
 * 调试日志函数。
 */
function debugLog(...args) {
    // 仅在 Frappe 开发者模式下输出日志
    if (window.frappe && frappe.boot && frappe.boot.developer_mode) {
        console.log('WeChatAuth Debug:', ...args);
    }
}

class WeChatAuth {
    /**
     * 构造函数
     * @param {object} options - 配置选项
     * @param {string} [options.authUrl] - 微信OAuth回调的后端方法
     * @param {string} [options.clientIdUrl] - 获取微信AppId的后端方法
     * @param {function} [options.onAuthSuccess] - 认证成功时的回调 (data: {wechat_userid: string})
     * @param {function} [options.onAuthError] - 认证失败时的回调 (message: string)
     * @param {string} [options.errorElementSelector] - 自动显示错误信息的DOM元素选择器
     */
    constructor(options = {}) {
        this.options = {
            authUrl: 'frappe_wxwork.wechat.callback.wechat_oauth_callback',
            clientIdUrl: 'frappe_wxwork.oauth2_logins.get_wx_client_id',
            onAuthSuccess: null,
            onAuthError: null,
            errorElementSelector: null,
            ...options
        };
        this.isWeChatBrowser = /micromessenger/i.test(navigator.userAgent);
        this.currentUserID = null;
        this.appId = null;
    }

    /**
     * 启动微信认证流程
     * @param {object} additionalParams - 需要在授权跳转中保留的【额外非认证参数】(如 {po: 'PO-0001', state: 'custom_flow'})
     */
    async initialize(additionalParams = {}) {
        debugLog('开始初始化');
        
        if (!this.isWeChatBrowser) {
            this.handleError('请在微信中打开此链接'); 
            return;
        }

        try {
            await this.loadWeChatClientId();
            
            const urlParams = new URLSearchParams(window.location.search);
            const code = urlParams.get('code'); 

            debugLog(`检测到参数 - code: ${code}`);

            if (code) {
                debugLog('检测到code参数，处理OAuth回调');
                // 仅传递 code，不传递任何业务参数
                await this.handleOAuthCallback(code);
            } else {
                debugLog('未检测到code参数，跳转到微信授权');
                // 跳转时携带所有 additionalParams
                await this.redirectToWeChatAuth(additionalParams);
            }
        } catch (error) {
            debugLog('初始化失败: ' + error.message);
            this.handleError(error.message);
        }
    }

    /**
     * 调用后端方法获取微信客户端ID (AppId)
     */
    async loadWeChatClientId() {
        if (this.appId) return this.appId;
        try {
            const response = await frappe.call({
                method: this.options.clientIdUrl,
                timeout: 10000 
            });
            if (response.message) {
                this.appId = response.message;
                return this.appId;
            } else {
                throw new Error(response.message?.error || '无法获取微信客户端ID');
            }
        } catch (error) {
            throw new Error('微信配置加载失败: ' + (error.message || '未知错误'));
        }
    }

    /**
     * 跳转到微信授权页面
     * @param {object} additionalParams - 需保留的额外 URL 参数 (包括可选的 state)
     */
    async redirectToWeChatAuth(additionalParams = {}) {
        try {
            if (!this.appId) throw new Error('微信客户端ID未初始化');

            // 构造重定向URL：保留额外的业务参数
            const currentUrl = window.location.href.split('?')[0]; 
            let redirectUrl = currentUrl;
            
            const params = new URLSearchParams();
            
            // 1. 处理所有 additionalParams (如 po)
            for (const [key, value] of Object.entries(additionalParams)) {
                if (value && key !== 'state') params.set(key, value);
            }
            if (params.toString()) {
                redirectUrl += `?${params.toString()}`;
            }
            
            const encodedUrl = encodeURIComponent(redirectUrl);
            
            // 2. 定义 state：优先使用 additionalParams.state，否则使用通用默认值
            const state = additionalParams.state || 'wechat_auth';
            
            // 3. 构造最终 OAuth URL
            const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${this.appId}&redirect_uri=${encodedUrl}&response_type=code&scope=snsapi_base&state=${state}#wechat_redirect`; 
            
            debugLog('授权URL: ' + authUrl);
            window.location.href = authUrl; 
            
        } catch (error) {
            debugLog('跳转授权页面失败: ' + error.message);
            this.handleError('微信认证配置错误: ' + error.message);
        }
    }

    /**
     * 处理微信OAuth回调 (验证code)
     * @param {string} code - 微信授权返回的code
     */
    async handleOAuthCallback(code) {
        try {
            debugLog('处理OAuth回调，code: ' + code);
            
            const response = await frappe.call({
                method: this.options.authUrl,
                args: { 
                    code: code,
                }, 
                timeout: 10000
            });

            if (response.message && response.message.success) { 
                this.currentUserID = response.message.wechat_userid; 
                debugLog('认证成功，用户ID: ' + this.currentUserID);
                
                // 清理 URL 中的认证参数 (code 和 state)，保留业务参数
                this.cleanAuthUrlParams(); 
                
                this.handleSuccess({
                    wechat_userid: this.currentUserID
                });
            } else {
                const errorMsg = response.message?.message || '微信认证失败';
                debugLog('认证失败: ' + errorMsg);
                throw new Error(errorMsg); 
            }
        } catch (error) {
            debugLog('OAuth回调处理失败: ' + error.message);
            
            if (error.message.includes('invalid code') || error.message.includes('40029')) {
                debugLog('code无效，2秒后重新授权');
                setTimeout(() => {
                    // 重新跳转，保留当前 URL 中的所有非认证参数
                    this.redirectToWeChatAuth(this.getBusinessParams()); 
                }, 2000);
            } else {
                this.handleError(error.message); 
            }
        }
    }

    /**
     * 辅助函数：获取当前 URL 中非认证相关的业务参数
     */
    getBusinessParams() {
        const url = new URL(window.location.href);
        const params = {};
        
        // 假设 code 和 state 是唯一的认证参数，其他都是业务参数
        url.searchParams.forEach((value, key) => {
            if (key !== 'code' && key !== 'state') {
                params[key] = value;
            }
        });
        return params;
    }


    /**
     * 清理 URL 中与认证相关的 code 和 state 参数
     */
    cleanAuthUrlParams() {
        if (window.history.replaceState) { 
            const url = new URL(window.location.href);
            url.searchParams.delete('code');
            url.searchParams.delete('state');
            
            const newUrl = url.toString();
            debugLog('清理认证URL参数，新URL: ' + newUrl);
            window.history.replaceState({}, document.title, newUrl); 
        }
    }

    /**
     * 触发成功回调
     */
    handleSuccess(data) {
        debugLog('触发成功回调: ' + JSON.stringify(data));
        if (this.options.onAuthSuccess && typeof this.options.onAuthSuccess === 'function') {
            this.options.onAuthSuccess(data);
        }
    }

    /**
     * 触发错误回调并处理 UI 显示
     */
    handleError(message) {
        debugLog('触发错误回调: ' + message);
        
        if (this.options.onAuthError && typeof this.options.onAuthError === 'function') {
            this.options.onAuthError(message);
        }

        if (this.options.errorElementSelector) {
            const $errorElement = $(this.options.errorElementSelector);
            if ($errorElement.length) {
                $errorElement.html(`<i class="fa fa-exclamation-triangle"></i> ${message}`).removeClass("hidden");
                $errorElement.show();
            } else {
                console.error('WeChatAuth Error: 无法找到指定的错误元素：' + this.options.errorElementSelector);
            }
        } else {
            console.error('微信认证错误: ' + message);
        }
    }

    getCurrentUserID() { return this.currentUserID; }
    getAppId() { return this.appId; }
}

// 导出到全局命名空间
frappe_wxwork.WeChatAuth = WeChatAuth;